home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / micrognu / part04 < prev    next >
Encoding:
Internet Message Format  |  1987-01-26  |  58.3 KB

  1. Subject:  v08i011:  A Micro-Emacs variant that resembles GNU Emacs
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Bob Larson <seismo!usc-oberon!blarson>
  6. Mod.sources: Volume 8, Issue 11
  7. Archive-name: micrognu/Part04
  8.  
  9.  
  10. #! /bin/sh
  11. # This is a shell archive, meaning:
  12. # 1. Remove everything above the #! /bin/sh line.
  13. # 2. Save the resulting text in a file.
  14. # 3. Execute the file with /bin/sh (not csh) to create the files:
  15. #    search.c
  16. #    symbol.c
  17. #    window.c
  18. #    tty/termcap/tty.c
  19. #    tty/termcap/readme
  20. #    tty/termcap/ttydef.h
  21. # This archive created: Sat Nov 15 15:06:50 1986
  22. export PATH; PATH=/bin:$PATH
  23. if test ! -d sys
  24. then
  25. mkdir sys
  26. fi
  27. if test ! -d tty
  28. then
  29. mkdir tty
  30. fi
  31. if test ! -d tty/termcap
  32. then
  33. mkdir tty/termcap
  34. fi
  35. if test -f 'search.c'
  36. then
  37.     echo shar: will not over-write existing file "'search.c'"
  38. else
  39. cat << \SHAR_EOF > 'search.c'
  40. /*
  41.  *         Search commands.
  42.  * The functions in this file implement the
  43.  * search commands (both plain and incremental searches
  44.  * are supported) and the query-replace command.
  45.  *
  46.  * The plain old search code is part of the original
  47.  * MicroEMACS "distribution". The incremental search code,
  48.  * and the query-replace code, is by Rich Ellison.
  49.  */
  50. #include    "def.h"
  51.  
  52. #define SRCH_BEGIN    (0)            /* Search sub-codes.    */
  53. #define    SRCH_FORW    (-1)
  54. #define SRCH_BACK    (-2)
  55. #define SRCH_NOPR    (-3)
  56. #define SRCH_ACCM    (-4)
  57. #define    SRCH_MARK    (-5)
  58.  
  59. typedef struct  {
  60.     int    s_code;
  61.     LINE    *s_dotp;
  62.     int    s_doto;
  63. }    SRCHCOM;
  64.  
  65. static    SRCHCOM    cmds[NSRCH];
  66. static    int    cip;
  67.  
  68. int    srch_lastdir = SRCH_NOPR;        /* Last search flags.    */
  69.  
  70. /*
  71.  * Search forward.
  72.  * Get a search string from the user, and search for it,
  73.  * starting at ".". If found, "." gets moved to just after the
  74.  * matched characters, and display does all the hard stuff.
  75.  * If not found, it just prints a message.
  76.  */
  77. /*ARGSUSED*/
  78. forwsearch(f, n, k) {
  79.     register int    s;
  80.  
  81.     if ((s=readpattern("Search")) != TRUE)
  82.         return (s);
  83.     if (forwsrch() == FALSE) {
  84.         ewprintf("Search failed: \"%s\"", pat);
  85.         return (FALSE);
  86.     }
  87.     srch_lastdir = SRCH_FORW;
  88.     return (TRUE);
  89. }
  90.  
  91. /*
  92.  * Reverse search.
  93.  * Get a search string from the  user, and search, starting at "."
  94.  * and proceeding toward the front of the buffer. If found "." is left
  95.  * pointing at the first character of the pattern [the last character that
  96.  * was matched].
  97.  */
  98. /*ARGSUSED*/
  99. backsearch(f, n, k) {
  100.     register int    s;
  101.  
  102.     if ((s=readpattern("Search backward")) != TRUE)
  103.         return (s);
  104.     if (backsrch() == FALSE) {
  105.         ewprintf("Search failed: \"%s\"", pat);
  106.         return (FALSE);
  107.     }
  108.     srch_lastdir = SRCH_BACK;
  109.     return (TRUE);
  110. }
  111.  
  112. /* 
  113.  * Search again, using the same search string
  114.  * and direction as the last search command. The direction
  115.  * has been saved in "srch_lastdir", so you know which way
  116.  * to go.
  117.  */
  118. /*ARGSUSED*/
  119. searchagain(f, n, k) {
  120.     if (srch_lastdir == SRCH_FORW) {
  121.         if (forwsrch() == FALSE) {
  122.             ewprintf("Search failed: \"%s\"", pat);
  123.             return (FALSE);
  124.         }
  125.         return (TRUE);
  126.     }
  127.     if (srch_lastdir == SRCH_BACK) {
  128.         if (backsrch() == FALSE) {
  129.             ewprintf("Search failed: \"%s\"", pat);
  130.             return (FALSE);
  131.         }
  132.         return (TRUE);
  133.     }
  134.     ewprintf("No last search");
  135.     return (FALSE);
  136. }
  137.  
  138. /*
  139.  * Use incremental searching, initially in the forward direction.
  140.  * isearch ignores any explicit arguments.
  141.  */
  142. /*ARGSUSED*/
  143. forwisearch(f, n, k) {
  144.     return (isearch(SRCH_FORW));
  145. }
  146.  
  147. /*
  148.  * Use incremental searching, initially in the reverse direction.
  149.  * isearch ignores any explicit arguments.
  150.  */
  151. /*ARGSUSED*/
  152. backisearch(f, n, k) {
  153.     return (isearch(SRCH_BACK));
  154. }
  155.  
  156. /*
  157.  * Incremental Search.
  158.  *    dir is used as the initial direction to search.
  159.  *    ^S    switch direction to forward
  160.  *    ^R    switch direction to reverse
  161.  *    ^Q    quote next character (allows searching for ^N etc.)
  162.  *    <ESC>    exit from Isearch
  163.  *    <DEL>    undoes last character typed. (tricky job to do this correctly).
  164.  *    other ^    exit search, don't set mark
  165.  *    else    accumulate into search string
  166.  */
  167. isearch(dir) {
  168.     register int    c;
  169.     register LINE    *clp;
  170.     register int    cbo;
  171.     register int    success;
  172.     int        pptr;
  173.     char        opat[NPAT];
  174.  
  175.     for (cip=0; cip<NSRCH; cip++)
  176.         cmds[cip].s_code = SRCH_NOPR;
  177.     (VOID) strcpy(opat, pat);
  178.     cip = 0;
  179.     pptr = -1;
  180.     clp = curwp->w_dotp;
  181.     cbo = curwp->w_doto;
  182.     is_lpush();
  183.     is_cpush(SRCH_BEGIN);
  184.     success = TRUE;
  185.     is_prompt(dir, TRUE, success);
  186.     for (;;) {
  187.         update();
  188.         switch (c = (char) getkey(KQUOTE)) {
  189.         case METACH:
  190.             srch_lastdir = dir;
  191.             curwp->w_markp = clp;
  192.             curwp->w_marko = cbo;
  193.             if (kbdmop == NULL) ewprintf("Mark set");
  194.             return (TRUE);
  195.  
  196.         case CCHR('G'):
  197.             if (success != TRUE) {
  198.                 while (is_peek() == SRCH_ACCM)
  199.                     if (is_undo(&pptr, &dir) == FALSE)
  200.                         break;
  201.                 success = TRUE;
  202.                 is_prompt(dir, pptr < 0, success);
  203.                 break;
  204.             }
  205.             curwp->w_dotp = clp;
  206.             curwp->w_doto = cbo;
  207.             curwp->w_flag |= WFMOVE;
  208.             srch_lastdir = dir;
  209.             (VOID) ctrlg(FALSE, 0, KRANDOM);
  210.             (VOID) strcpy(pat, opat);
  211.             return ABORT;
  212.  
  213.         case CCHR('S'):
  214.             if (dir == SRCH_BACK) {
  215.                 dir = SRCH_FORW;
  216.                 is_lpush();
  217.                 is_cpush(SRCH_FORW);
  218.                 success = TRUE;
  219.             }
  220.             if (success==FALSE && dir==SRCH_FORW)
  221.                 break;
  222.             is_lpush();
  223.             pptr = strlen(pat);
  224.             (VOID) forwchar(FALSE, 1, KRANDOM);
  225.             if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK);
  226.             else {
  227.                 (VOID) backchar(FALSE, 1, KRANDOM);
  228.                 ttbeep();
  229.                 success = FALSE;
  230.             }
  231.             is_prompt(dir, pptr < 0, success);
  232.             break;
  233.  
  234.         case CCHR('R'):
  235.             if (dir == SRCH_FORW) {
  236.                 dir = SRCH_BACK;
  237.                 is_lpush();
  238.                 is_cpush(SRCH_BACK);
  239.                 success = TRUE;
  240.             }
  241.             if (success==FALSE && dir==SRCH_BACK)
  242.                 break;
  243.             is_lpush();
  244.             pptr = strlen(pat);
  245.             (VOID) backchar(FALSE, 1, KRANDOM);
  246.             if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK);
  247.             else {
  248.                 (VOID) forwchar(FALSE, 1, KRANDOM);
  249.                 ttbeep();
  250.                 success = FALSE;
  251.             }
  252.             is_prompt(dir, pptr < 0, success);
  253.             break;
  254.  
  255.         case 0x7F:
  256.             if (is_undo(&pptr, &dir) != TRUE) return FALSE;
  257.             if (is_peek() != SRCH_ACCM) success = TRUE;
  258.             is_prompt(dir, pptr < 0, success);
  259.             break;
  260.  
  261.         case CCHR('Q'):
  262.             c = (char) getkey(KQUOTE);
  263.             goto  addchar;
  264.         case CCHR('M'):
  265.             c = CCHR('J');
  266.         case CCHR('J'):
  267.             goto  addchar;
  268.  
  269.         default:
  270.             if (ISCTRL(c) != FALSE) {
  271.                 c += '@';
  272.                 c |= KCTRL;
  273.                 success = execute((KEY) c, FALSE, 1);
  274.                 curwp->w_markp = clp;
  275.                 curwp->w_marko = cbo;
  276.                 if (kbdmop == NULL) ewprintf("Mark set");
  277.                 curwp->w_flag |= WFMOVE;
  278.                 return (success);
  279.             }                
  280.         addchar:
  281.             if (pptr == -1)
  282.                 pptr = 0;
  283.             if (pptr == 0)
  284.                 success = TRUE;
  285.             pat[pptr++] = c;
  286.             if (pptr == NPAT) {
  287.                 ewprintf("Pattern too long");
  288.                 return FALSE;
  289.             }
  290.             pat[pptr] = '\0';
  291.             is_lpush();
  292.             if (success != FALSE) {
  293.                 if (is_find(dir) != FALSE)
  294.                     is_cpush(c);
  295.                 else {
  296.                     success = FALSE;
  297.                     ttbeep();
  298.                     is_cpush(SRCH_ACCM);
  299.                 }
  300.             } else
  301.                 is_cpush(SRCH_ACCM);
  302.             is_prompt(dir, FALSE, success);
  303.         }
  304.     }
  305. }
  306.  
  307. is_cpush(cmd) register int cmd; {
  308.     if (++cip >= NSRCH)
  309.         cip = 0;
  310.     cmds[cip].s_code = cmd;
  311. }
  312.  
  313. is_lpush() {
  314.     register int    ctp;
  315.  
  316.     ctp = cip+1;
  317.     if (ctp >= NSRCH)
  318.         ctp = 0;
  319.     cmds[ctp].s_code = SRCH_NOPR;
  320.     cmds[ctp].s_doto = curwp->w_doto;
  321.     cmds[ctp].s_dotp = curwp->w_dotp;
  322. }
  323.  
  324. is_pop() {
  325.     if (cmds[cip].s_code != SRCH_NOPR) {
  326.         curwp->w_doto  = cmds[cip].s_doto; 
  327.         curwp->w_dotp  = cmds[cip].s_dotp;
  328.         curwp->w_flag |= WFMOVE;
  329.         cmds[cip].s_code = SRCH_NOPR;
  330.     }
  331.     if (--cip <= 0)
  332.         cip = NSRCH-1;
  333. }
  334.  
  335. is_peek() {
  336.     return cmds[cip].s_code;
  337. }
  338.  
  339. is_undo(pptr, dir) register int *pptr; register int *dir; {
  340.     register int    redo = FALSE ;
  341.     switch (cmds[cip].s_code) {
  342.     case SRCH_BEGIN:
  343.     case SRCH_NOPR:
  344.         *pptr = -1;
  345.     case SRCH_MARK:
  346.         break;
  347.  
  348.     case SRCH_FORW:
  349.         *dir = SRCH_BACK;
  350.         redo = TRUE;
  351.         break;
  352.  
  353.     case SRCH_BACK:
  354.         *dir = SRCH_FORW;
  355.         redo = TRUE;
  356.         break;
  357.  
  358.     case SRCH_ACCM:
  359.     default:
  360.         *pptr -= 1;
  361.         if (*pptr < 0)
  362.             *pptr = 0;
  363.         pat[*pptr] = '\0';
  364.         break;
  365.     }
  366.     is_pop();
  367.     if (redo) return is_undo(pptr, dir);
  368.     return (TRUE);
  369. }
  370.  
  371. is_find(dir) register int dir; {
  372.     register int    plen, odoto;
  373.     register LINE    *odotp ;
  374.  
  375.     odoto = curwp->w_doto;
  376.     odotp = curwp->w_dotp;
  377.     plen = strlen(pat);
  378.     if (plen != 0) {
  379.         if (dir==SRCH_FORW) {
  380.             (VOID) backchar(TRUE, plen, KRANDOM);
  381.             if (forwsrch() == FALSE) {
  382.                 curwp->w_doto = odoto;
  383.                 curwp->w_dotp = odotp;
  384.                 return (FALSE);
  385.             }
  386.             return (TRUE);
  387.         }
  388.         if (dir==SRCH_BACK) {
  389.             (VOID) forwchar(TRUE, plen, KRANDOM);
  390.             if (backsrch() == FALSE) {
  391.                 curwp->w_doto = odoto;
  392.                 curwp->w_dotp = odotp;
  393.                 return (FALSE);
  394.             }
  395.             return (TRUE);
  396.         }
  397.         ewprintf("bad call to is_find");
  398.         return FALSE;
  399.     }
  400.     return (FALSE);
  401. }
  402.  
  403. /*
  404.  * If called with "dir" not one of SRCH_FORW
  405.  * or SRCH_BACK, this routine used to print an error
  406.  * message. It also used to return TRUE or FALSE,
  407.  * depending on if it liked the "dir". However, none
  408.  * of the callers looked at the status, so I just
  409.  * made the checking vanish.
  410.  */
  411. is_prompt(dir, flag, success) {
  412.     VOID is_dspl();
  413.  
  414.     if (dir == SRCH_FORW) {
  415.         if (success != FALSE)
  416.             is_dspl("I-search", flag);
  417.         else
  418.             is_dspl("Failing I-search", flag);
  419.     } else if (dir == SRCH_BACK) {
  420.         if (success != FALSE)
  421.             is_dspl("I-search backward", flag);
  422.         else
  423.             is_dspl("Failing I-search backward", flag);
  424.     } else ewprintf("Broken call to is_prompt");
  425. }
  426.  
  427. /*
  428.  * Prompt writing routine for the incremental search. 
  429.  * The "prompt" is just a string. The "flag" determines
  430.  * whether pat should be printed.
  431.  */
  432. VOID
  433. is_dspl(prompt, flag) char *prompt; {
  434.  
  435.     if (kbdmop != NULL) return;
  436.     if (flag != FALSE)
  437.         ewprintf("%s: ", prompt);
  438.     else
  439.         ewprintf("%s: %s", prompt, pat);
  440. }
  441.  
  442. /*
  443.  * Query Replace.
  444.  *    Replace strings selectively.  Does a search and replace operation.
  445.  */
  446. /*ARGSUSED*/
  447. queryrepl(f, n, k) {
  448.     register int    s;
  449.     register int    rcnt = 0;    /* Replacements made so far    */
  450.     register int    plen;        /* length of found string    */
  451.     char        news[NPAT];    /* replacement string        */
  452.  
  453.     if ((s=readpattern("Query replace")) != TRUE)
  454.         return (s);
  455.     if ((s=ereply("Query replace %s with: ",news, NPAT, pat)) == ABORT)
  456.         return (s);
  457.     if (s == FALSE)
  458.         news[0] = '\0';
  459.     if (kbdmop == NULL) ewprintf("Query replacing %s with %s:", pat, news);
  460.     plen = strlen(pat);
  461.  
  462.     /*
  463.      * Search forward repeatedly, checking each time whether to insert
  464.      * or not.  The "!" case makes the check always true, so it gets put
  465.      * into a tighter loop for efficiency.
  466.      */
  467.  
  468.     while (forwsrch() == TRUE) {
  469.     retry:
  470.         update();
  471.         switch (getkey(KQUOTE)) {
  472.         case ' ':
  473.             if (lreplace((RSIZE) plen, news, f) == FALSE)
  474.                 return (FALSE);
  475.             rcnt++;
  476.             break;
  477.  
  478.         case '.':
  479.             if (lreplace((RSIZE) plen, news, f) == FALSE)
  480.                 return (FALSE);
  481.             rcnt++;
  482.             goto stopsearch;
  483.  
  484.         case CCHR('G'):    /* ^G or ESC */
  485.             (VOID) ctrlg(FALSE, 0, KRANDOM);
  486.         case 033:
  487.             goto stopsearch;
  488.  
  489.         case '!':
  490.             do {
  491.                 if (lreplace((RSIZE) plen, news, f) == FALSE)
  492.                     return (FALSE);
  493.                 rcnt++;
  494.             } while (forwsrch() == TRUE);
  495.             goto stopsearch;
  496.  
  497.         case 0x7F:        /* To not replace */
  498.             break;
  499.  
  500.         default:
  501. ewprintf("<SP> replace, [.] rep-end, <DEL> don't, [!] repl rest <ESC> quit");
  502.             goto retry;
  503.         }
  504.     }
  505. stopsearch:
  506.     curwp->w_flag |= WFHARD;
  507.     update();
  508.     if (kbdmop == NULL) {
  509.         if (rcnt == 0)
  510.             ewprintf("(No replacements done)");
  511.         else if (rcnt == 1)
  512.             ewprintf("(1 replacement done)");
  513.         else
  514.             ewprintf("(%d replacements done)", rcnt);
  515.     }
  516.     return TRUE;
  517. }
  518.  
  519. /*
  520.  * This routine does the real work of a
  521.  * forward search. The pattern is sitting in the external
  522.  * variable "pat". If found, dot is updated, the window system
  523.  * is notified of the change, and TRUE is returned. If the
  524.  * string isn't found, FALSE is returned.
  525.  */
  526. forwsrch() {
  527.     register LINE    *clp;
  528.     register int    cbo;
  529.     register LINE    *tlp;
  530.     register int    tbo;
  531.     register char    *pp;
  532.     register int    c;
  533.  
  534.     clp = curwp->w_dotp;
  535.     cbo = curwp->w_doto;
  536.     while (clp != curbp->b_linep) {
  537.         if (cbo == llength(clp)) {
  538.             clp = lforw(clp);
  539.             cbo = 0;
  540.             c = SEOL;
  541.         } else
  542.             c = lgetc(clp, cbo++);
  543.         if (eq(c, pat[0]) != FALSE) {
  544.             tlp = clp;
  545.             tbo = cbo;
  546.             pp  = &pat[1];
  547.             while (*pp != 0) {
  548.                 if (tlp == curbp->b_linep)
  549.                     goto fail;
  550.                 if (tbo == llength(tlp)) {
  551.                     tlp = lforw(tlp);
  552.                     if (tlp == curbp->b_linep)
  553.                         goto fail;
  554.                     tbo = 0;
  555.                     c = SEOL;
  556.                 } else
  557.                     c = lgetc(tlp, tbo++);
  558.                 if (eq(c, *pp++) == FALSE)
  559.                     goto fail;
  560.             }
  561.             curwp->w_dotp  = tlp;
  562.             curwp->w_doto  = tbo;
  563.             curwp->w_flag |= WFMOVE;
  564.             return (TRUE);
  565.         }
  566.     fail:    ;
  567.     }
  568.     return (FALSE);
  569. }
  570.  
  571. /*
  572.  * This routine does the real work of a
  573.  * backward search. The pattern is sitting in the external
  574.  * variable "pat". If found, dot is updated, the window system
  575.  * is notified of the change, and TRUE is returned. If the
  576.  * string isn't found, FALSE is returned.
  577.  */
  578. backsrch() {
  579.     register LINE    *clp;
  580.     register int    cbo;
  581.     register LINE    *tlp;
  582.     register int    tbo;
  583.     register int    c;
  584.     register char    *epp;
  585.     register char    *pp;
  586.  
  587.     for (epp = &pat[0]; epp[1] != 0; ++epp)
  588.         ;
  589.     clp = curwp->w_dotp;
  590.     cbo = curwp->w_doto;
  591.     for (;;) {
  592.         if (cbo == 0) {
  593.             clp = lback(clp);
  594.             if (clp == curbp->b_linep)
  595.                 return (FALSE);
  596.             cbo = llength(clp)+1;
  597.         }
  598.         if (--cbo == llength(clp))
  599.             c = SEOL;
  600.         else
  601.             c = lgetc(clp,cbo);
  602.         if (eq(c, *epp) != FALSE) {
  603.             tlp = clp;
  604.             tbo = cbo;
  605.             pp  = epp;
  606.             while (pp != &pat[0]) {
  607.                 if (tbo == 0) {
  608.                     tlp = lback(tlp);
  609.                     if (tlp == curbp->b_linep)
  610.                         goto fail;
  611.                     tbo = llength(tlp)+1;
  612.                 }
  613.                 if (--tbo == llength(tlp))
  614.                     c = SEOL;
  615.                 else
  616.                     c = lgetc(tlp,tbo);
  617.                 if (eq(c, *--pp) == FALSE)
  618.                     goto fail;
  619.             }
  620.             curwp->w_dotp  = tlp;
  621.             curwp->w_doto  = tbo;
  622.             curwp->w_flag |= WFMOVE;
  623.             return (TRUE);
  624.         }
  625.     fail:    ;
  626.     }
  627. }
  628.  
  629. /*
  630.  * Compare two characters.
  631.  * The "bc" comes from the buffer.
  632.  * It has its case folded out. The
  633.  * "pc" is from the pattern.
  634.  */
  635. eq(bc, pc) {
  636.     register int    ibc;
  637.     register int    ipc;
  638.  
  639.     ibc = bc & 0xFF;
  640.     ipc = pc & 0xFF;
  641.     if (ISLOWER(ibc) != FALSE)
  642.         ibc = TOUPPER(ibc);
  643.     if (ISLOWER(ipc) != FALSE)
  644.         ipc = TOUPPER(ipc);
  645.     if (ibc == ipc)
  646.         return (TRUE);
  647.     return (FALSE);
  648. }
  649.  
  650. /*
  651.  * Read a pattern.
  652.  * Stash it in the external variable "pat". The "pat" is
  653.  * not updated if the user types in an empty line. If the user typed
  654.  * an empty line, and there is no old pattern, it is an error.
  655.  * Display the old pattern, in the style of Jeff Lomicka. There is
  656.  * some do-it-yourself control expansion.
  657.  */
  658. readpattern(prompt) char *prompt; {
  659.     register int    s;
  660.     char        tpat[NPAT];
  661.  
  662.     if (tpat[0] == '\0') s = ereply("%s: ", tpat, NPAT, prompt);
  663.     else s = ereply("%s: (default %s) ", tpat, NPAT, prompt, pat);
  664.  
  665.     if (s == TRUE)                /* Specified        */
  666.         (VOID) strcpy(pat, tpat);
  667.     else if (s==FALSE && pat[0]!=0)        /* CR, but old one    */
  668.         s = TRUE;
  669.     return (s);
  670. }
  671. SHAR_EOF
  672. fi # end of overwriting check
  673. if test -f 'symbol.c'
  674. then
  675.     echo shar: will not over-write existing file "'symbol.c'"
  676. else
  677. cat << \SHAR_EOF > 'symbol.c'
  678. /*
  679.  * Symbol tables, and keymap setup.
  680.  * The terminal specific parts of building the
  681.  * keymap has been moved to a better place.
  682.  */
  683. #include    "def.h"
  684.  
  685. #ifdef    HASH
  686. Since you're seeing this, you must have defined HASH to try and get the
  687. hashing code back. You're getting an error because I (mwm@ucbvax) want you
  688. to read this.
  689.  
  690. With the change in function completion, there is at least one linear search
  691. through the function list for every hash lookup (ignoring the startup code).
  692. Given that there are probably actually MANY more linear searches for
  693. completion than fullname lookups, some structure other than a hash table is
  694. better suited to this purpose. I suggest trying sorting the lists for more
  695. speed, then going to a binary search tree, and finally going to a trie.
  696. #endif    HASH
  697.  
  698. /*
  699.  * Defined here so to collect the #ifdef MEYN config stuff in one file
  700.  * If you set either MINDENT or MFILL, then you need to change the bindings
  701.  * in this file to match: KCTRL|'M' -> newline-and-indent and KCTRL|'J' ->
  702.  * insert-newline for MINDENT, and ' ' -> insert-with-wrap for MFILL.
  703.  * MEYN is used for compile-time customization of the system for micros.
  704.  */
  705. #ifndef    MEYN
  706. int    mode = 0;            /* All modes off        */
  707. #else
  708. int    mode = MBSMAP|MINDENT;
  709. #endif
  710.  
  711. /*
  712.  * Defined by "main.c".
  713.  */
  714. extern    int    ctrlg();        /* Abort out of things        */
  715. extern    int    quit();            /* Quit                */
  716. extern    int    ctlxlp();        /* Begin macro            */
  717. extern    int    ctlxrp();        /* End macro            */
  718. extern    int    ctlxe();        /* Execute macro        */
  719. extern  int    showversion();        /* Show version numbers, etc.    */
  720.  
  721. /*
  722.  * Defined by "search.c".
  723.  */
  724. extern    int    forwsearch();        /* Search forward        */
  725. extern    int    backsearch();        /* Search backwards        */
  726. extern  int    searchagain();        /* Repeat last search command    */
  727. extern  int    forwisearch();        /* Incremental search forward    */
  728. extern  int    backisearch();        /* Incremental search backwards    */
  729. extern  int    queryrepl();        /* Query replace        */
  730.  
  731. /*
  732.  * Defined by "basic.c".
  733.  */
  734. extern    int    gotobol();        /* Move to start of line    */
  735. extern    int    backchar();        /* Move backward by characters    */
  736. extern    int    gotoeol();        /* Move to end of line        */
  737. extern    int    forwchar();        /* Move forward by characters    */
  738. extern    int    gotobob();        /* Move to start of buffer    */
  739. extern    int    gotoeob();        /* Move to end of buffer    */
  740. extern    int    forwline();        /* Move forward by lines    */
  741. extern    int    backline();        /* Move backward by lines    */
  742. extern    int    forwpage();        /* Move forward by pages    */
  743. extern    int    backpage();        /* Move backward by pages    */
  744. extern    int    pagenext();        /* Page forward next window    */
  745. extern    int    setmark();        /* Set mark            */
  746. extern    int    swapmark();        /* Swap "." and mark        */
  747. extern    int    gotoline();        /* Go to a specified line.    */
  748.  
  749. /*
  750.  * Defined by "buffer.c".
  751.  */
  752. extern    int    listbuffers();        /* Display list of buffers    */
  753. extern    int    usebuffer();        /* Switch a window to a buffer    */
  754. extern    int    poptobuffer();        /* Other window to a buffer    */
  755. extern    int    killbuffer();        /* Make a buffer go away.    */
  756. extern    int    savebuffers();        /* Save unmodified buffers    */
  757. extern    int    bufferinsert();        /* Insert buffer into another    */
  758. extern    int    notmodified();        /* Reset modification flag    */
  759.  
  760. #ifdef    DIRLIST
  761. /*
  762.  * Defined by "dirlist.c".
  763.  */
  764. extern    int    dirlist();        /* Directory list.        */
  765. #endif
  766.  
  767. /*
  768.  * Defined by "file.c".
  769.  */
  770. extern    int    filevisit();        /* Get a file, read write    */
  771. extern    int    poptofile();        /* Get a file, other window    */
  772. extern    int    filewrite();        /* Write a file            */
  773. extern    int    filesave();        /* Save current file        */
  774. extern    int    fileinsert();        /* Insert file into buffer    */
  775.  
  776. /*
  777.  * Defined by "match.c"
  778.  */
  779. extern    int    blinkparen();        /* Fake blink-matching-paren var */
  780. extern    int    showmatch();        /* Hack to show matching paren     */
  781.  
  782. /*
  783.  * Defined by "random.c".
  784.  */
  785. extern    int    selfinsert();        /* Insert character        */
  786. extern    int    showcpos();        /* Show the cursor position    */
  787. extern    int    twiddle();        /* Twiddle characters        */
  788. extern    int    quote();        /* Insert literal        */
  789. extern    int    openline();        /* Open up a blank line        */
  790. extern    int    newline();        /* Insert CR-LF            */
  791. extern    int    deblank();        /* Delete blank lines        */
  792. extern    int    delwhite();        /* Delete extra whitespace    */
  793. extern    int    indent();        /* Insert CR-LF, then indent    */
  794. extern    int    forwdel();        /* Forward delete        */
  795. extern    int    backdel();        /* Backward delete in        */
  796. extern    int    killline();        /* Kill forward            */
  797. extern    int    yank();            /* Yank back from killbuffer.    */
  798. extern    int    bsmapmode();        /* set bsmap mode        */
  799. extern    int    flowmode();        /* set flow mode        */
  800. extern    int    indentmode();        /* set auto-indent mode        */
  801. extern    int    fillmode();        /* set word-wrap mode        */
  802.  
  803. /*
  804.  * Defined by "region.c".
  805.  */
  806. extern    int    killregion();        /* Kill region.            */
  807. extern    int    copyregion();        /* Copy region to kill buffer.    */
  808. extern    int    lowerregion();        /* Lower case region.        */
  809. extern    int    upperregion();        /* Upper case region.        */
  810. #ifdef    PREFIXREGION
  811. extern    int    prefixregion();        /* Prefix all lines in region    */
  812. extern    int    setprefix();        /* Set line prefix string    */
  813. #endif
  814.  
  815. /*
  816.  * Defined by "spawn.c".
  817.  */
  818. extern    int    spawncli();        /* Run CLI in a subjob.        */
  819. #ifdef    VMS
  820. extern    int    attachtoparent();    /* Attach to parent process    */
  821. #endif
  822.  
  823. /*
  824.  * Defined by "window.c".
  825.  */
  826. extern    int    reposition();        /* Reposition window        */
  827. extern    int    refresh();        /* Refresh the screen        */
  828. extern    int    nextwind();        /* Move to the next window    */
  829. extern  int    prevwind();        /* Move to the previous window    */
  830. extern    int    onlywind();        /* Make current window only one    */
  831. extern    int    splitwind();        /* Split current window        */
  832. extern    int    delwind();        /* Delete current window    */
  833. extern    int    enlargewind();        /* Enlarge display window.    */
  834. extern    int    shrinkwind();        /* Shrink window.        */
  835.  
  836. /*
  837.  * Defined by "word.c".
  838.  */
  839. extern    int    backword();        /* Backup by words        */
  840. extern    int    forwword();        /* Advance by words        */
  841. extern    int    upperword();        /* Upper case word.        */
  842. extern    int    lowerword();        /* Lower case word.        */
  843. extern    int    capword();        /* Initial capitalize word.    */
  844. extern    int    delfword();        /* Delete forward word.        */
  845. extern    int    delbword();        /* Delete backward word.    */
  846.  
  847. /*
  848.  * Defined by "extend.c".
  849.  */
  850. extern    int    extend();        /* Extended commands.        */
  851. extern    int    desckey();        /* Help key.            */
  852. extern    int    bindtokey();        /* Modify key bindings.        */
  853. extern    int    unsetkey();        /* Unbind a key.        */
  854. extern    int    wallchart();        /* Make wall chart.        */
  855. #ifdef    STARTUP
  856. extern    int    evalexpr();        /* Extended commands (again)    */
  857. extern    int    evalbuffer();        /* Evaluate current buffer    */
  858. extern    int    evalfile();        /* Evaluate a file        */
  859. #endif
  860.  
  861. /*
  862.  * defined by "paragraph.c" - the paragraph justification code.
  863.  */
  864. extern    int    gotobop();        /* Move to start of paragraph.    */
  865. extern    int    gotoeop();        /* Move to end of paragraph.    */
  866. extern    int    fillpara();        /* Justify a paragraph.        */
  867. extern    int    killpara();        /* Delete a paragraph.        */
  868. extern    int    setfillcol();        /* Set fill column for justify.    */
  869. extern    int    fillword();        /* Insert char with word wrap.    */
  870.  
  871. /*
  872.  * defined by prefix.c
  873.  */
  874. extern    int    help();            /* Parse help key.        */
  875. extern    int    ctlx4hack();        /* Parse a pop-to key.        */
  876.  
  877. typedef    struct    {
  878.     KEY    k_key;            /* Key to bind.            */
  879.     int    (*k_funcp)();        /* Function.            */
  880.     char    *k_name;        /* Function name string.    */
  881. }    KEYTAB;
  882.  
  883. /*
  884.  * Default key binding table. This contains
  885.  * the function names, the symbol table name, and (possibly)
  886.  * a key binding for the builtin functions. There are no
  887.  * bindings for C-U or C-X. These are done with special
  888.  * code, but should be done normally.
  889.  */
  890. KEYTAB    key[] = {
  891. #ifdef    MEYN        /* Add meyer's peculiar bindings */
  892.     KCTRL|'J',    newline,    "insert-newline",
  893.     KCTRL|'M',    indent,        "newline-and-indent",
  894.     KCTLX|'N',    nextwind,     "next-window",
  895.     KCTLX|'P',    prevwind,    "previous-window",
  896.     KMETA|KCTRL|'C',quit,        "save-buffers-kill-emacs",
  897.     KMETA|KCTRL|'L',refresh,    "redraw-display",
  898.     KMETA|'G',    gotoline,    "goto-line",
  899.     KMETA|'J',    fillpara,    "fill-paragraph",
  900.     KMETA|'Q',    queryrepl,    "query-replace",
  901. #endif
  902.     KCTRL|'@',    setmark,    "set-mark-command",
  903.     KCTRL|'A',    gotobol,    "beginning-of-line",
  904.     KCTRL|'B',    backchar,    "backward-char",
  905.     KCTRL|'D',    forwdel,    "delete-char",
  906.     KCTRL|'E',    gotoeol,    "end-of-line",
  907.     KCTRL|'F',    forwchar,    "forward-char",
  908.     KCTRL|'G',    ctrlg,        "keyboard-quit",
  909.     KCTRL|'H',    help,        "help",
  910.     KCTRL|'I',    selfinsert,    "self-insert-command",
  911. #ifndef    MEYN
  912.     KCTRL|'J',    indent,        "newline-and-indent",
  913. #endif
  914.     KCTRL|'L',    reposition,    "recenter",
  915.     KCTRL|'K',    killline,    "kill-line",
  916. #ifndef    MEYN
  917.     KCTRL|'M',    newline,    "insert-newline",
  918. #endif
  919.     KCTRL|'N',    forwline,    "next-line",
  920.     KCTRL|'O',    openline,    "open-line",
  921.     KCTRL|'P',    backline,    "previous-line",
  922.     KCTRL|'Q',    quote,        "quoted-insert",
  923.     KCTRL|'R',    backisearch,    "isearch-backward",
  924.     KCTRL|'S',    forwisearch,    "isearch-forward",
  925.     KCTRL|'T',    twiddle,    "transpose-chars",
  926.     KCTRL|'V',    forwpage,    "scroll-up",
  927.     KCTRL|'W',    killregion,    "kill-region",
  928.     KCTRL|'Y',    yank,        "yank",
  929. #ifdef    VMS
  930.     KCTRL|'Z',    attachtoparent,    "suspend-emacs",
  931. #else
  932.     KCTRL|'Z',    spawncli,    "suspend-emacs",
  933. #endif
  934.     KCTLX|KCTRL|'B',listbuffers,    "list-buffers",
  935. #ifndef    MEYN
  936.     KCTLX|KCTRL|'C',quit,        "save-buffers-kill-emacs",
  937. #endif
  938. #ifdef    DIRLIST
  939.     KCTLX|KCTRL|'D',dirlist,    "display-directory",
  940. #endif
  941.     KCTLX|KCTRL|'F',filevisit,    "find-file",
  942.     KCTLX|KCTRL|'L',lowerregion,    "downcase-region",
  943.     KCTLX|KCTRL|'O',deblank,    "delete-blank-lines",
  944.     KCTLX|KCTRL|'S',filesave,    "save-buffer",
  945.     KCTLX|KCTRL|'U',upperregion,    "upcase-region",
  946.     KCTLX|KCTRL|'W',filewrite,    "write-file",
  947.     KCTLX|KCTRL|'X',swapmark,    "exchange-point-and-mark",
  948.     KCTLX|'=',    showcpos,    "what-cursor-position",
  949.     KCTLX|'(',    ctlxlp,        "start-kbd-macro",
  950.     KCTLX|')',    ctlxrp,        "end-kbd-macro",
  951.     KCTLX|'^',    enlargewind,    "enlarge-window",
  952.     KCTLX|'0',    delwind,    "delete-window",
  953.     KCTLX|'1',    onlywind,    "delete-other-windows",
  954.     KCTLX|'2',    splitwind,    "split-window-vertically",
  955.     KCTLX|'4',    ctlx4hack,    "ctrlx-four-hack",
  956.     KCTLX|'B',    usebuffer,    "switch-to-buffer",
  957.     KCTLX|'E',    ctlxe,        "call-last-kbd-macro",
  958.     KCTLX|'F',    setfillcol,    "set-fill-column",
  959.     KCTLX|'I',    fileinsert,    "insert-file",
  960.     KCTLX|'K',    killbuffer,    "kill-buffer",
  961.     KCTLX|'S',    savebuffers,    "save-some-buffers",
  962. #ifndef    MEYN
  963.     KCTLX|'O',    nextwind,    "next-window",
  964.     KMETA|'%',    queryrepl,    "query-replace",
  965. #endif
  966.     KMETA|KCTRL|'V',pagenext,    "scroll-other-window",
  967.     KMETA|'>',    gotoeob,    "end-of-buffer",
  968.     KMETA|'<',    gotobob,    "beginning-of-buffer",
  969.     KMETA|'[',    gotobop,    "backward-paragraph",
  970.     KMETA|']',    gotoeop,    "forward-paragraph",
  971.     KMETA|' ',    delwhite,    "just-one-space",
  972.     KMETA|'B',    backword,    "backward-word",
  973.     KMETA|'C',    capword,    "capitalize-word",
  974.     KMETA|'D',    delfword,    "kill-word",
  975.     KMETA|'F',    forwword,    "forward-word",
  976.     KMETA|'L',    lowerword,    "downcase-word",
  977. #ifndef    MEYN
  978.     KMETA|'Q',    fillpara,    "fill-paragraph",
  979. #endif
  980.     KMETA|'R',    backsearch,    "search-backward",
  981.     KMETA|'S',    forwsearch,    "search-forward",
  982.     KMETA|'U',    upperword,    "upcase-word",
  983.     KMETA|'V',    backpage,    "scroll-down",
  984.     KMETA|'W',    copyregion,    "copy-region-as-kill",
  985.     KMETA|'X',    extend,        "execute-extended-command",
  986.     KMETA|'~',    notmodified,    "not-modified",
  987. #ifndef    MEYN
  988.     -1,        prevwind,    "previous-window",
  989.     -1,        refresh,    "redraw-display",
  990.     -1,        gotoline,    "goto-line",
  991. #endif
  992. #ifdef    STARTUP
  993.     -1,        evalexpr,    "eval-expression",
  994.     -1,        evalbuffer,    "eval-current-buffer",
  995.     -1,        evalfile,    "load",
  996. #endif
  997.     -1,        bsmapmode,    "bsmap-mode",
  998.     -1,        flowmode,    "flow-mode",
  999.     -1,        indentmode,    "auto-indent-mode",
  1000.     -1,        fillmode,    "auto-fill-mode",
  1001.     -1,        fillword,    "insert-with-wrap",
  1002.     -1,        shrinkwind,    "shrink-window",
  1003.     -1,        searchagain,    "search-again",
  1004.     -1,        unsetkey,    "global-unset-key",
  1005.     -1,        bindtokey,    "global-set-key",
  1006.     -1,        killpara,    "kill-paragraph",
  1007.     -1,        showversion,    "emacs-version",
  1008.     -1,        blinkparen,    "blink-matching-paren",
  1009.     -1,        showmatch,    "blink-matching-paren-hack",
  1010.     -1,        bufferinsert,    "insert-buffer",
  1011. #ifdef    VMS
  1012.     -1,        spawncli,    "push-to-dcl",
  1013. #endif
  1014. #ifdef    PREFIXREGION
  1015.     -1,        prefixregion,    "prefix-region",
  1016.     -1,        setprefix,    "set-prefix-string",
  1017. #endif
  1018.     /* You can actually get to these with keystrokes. See prefix.c */
  1019.     -1,        poptobuffer,    "switch-to-buffer-other-window",
  1020.     -1,        poptofile,    "find-file-other-window",
  1021.     -1,        desckey,    "describe-key-briefly",
  1022.     -1,        wallchart,    "describe-bindings",
  1023. };
  1024.  
  1025. #define    NKEY    (sizeof(key) / sizeof(key[0]))
  1026.  
  1027. /*
  1028.  * Symbol table lookup.
  1029.  * Return a pointer to the SYMBOL node, or NULL if
  1030.  * the symbol is not found.
  1031.  */
  1032. SYMBOL    *
  1033. symlookup(cp) register char *cp; {
  1034.     register SYMBOL    *sp;
  1035.  
  1036. #ifdef    HASH
  1037.     sp = symbol[symhash(cp)];
  1038. #else
  1039.     sp = symbol[0];
  1040. #endif
  1041.     while (sp != NULL) {
  1042.         if (strcmp(cp, sp->s_name) == 0)
  1043.             return (sp);
  1044. #ifdef    HASH
  1045.         if ((sp->s_flags&SFEND) != 0) break;
  1046. #endif
  1047.         sp = sp->s_symp;
  1048.     }
  1049.     return (NULL);
  1050. }
  1051.  
  1052. #ifdef    HASH
  1053. /*
  1054.  * Take a string, and compute the symbol table
  1055.  * bucket number. This is done by adding all of the characters
  1056.  * together, and taking the sum mod NSHASH. The string probably
  1057.  * should not contain any GR characters; if it does the "*cp"
  1058.  * may get a nagative number on some machines, and the "%"
  1059.  * will return a negative number!
  1060.  */
  1061. symhash(cp) register char *cp; {
  1062.     register int    c;
  1063.     register int    n;
  1064.  
  1065.     n = 0;
  1066.     while ((c = *cp++) != 0)
  1067.         n += c;
  1068.     return (n % NSHASH);
  1069. }
  1070. #endif
  1071.  
  1072. /*
  1073.  * Build initial keymap. The funny keys
  1074.  * (commands, odd control characters) are mapped using
  1075.  * a big table and calls to "keyadd". The printing characters
  1076.  * are done with some do-it-yourself handwaving. The terminal
  1077.  * specific keymap initialization code is called at the
  1078.  * very end to finish up. All errors are fatal.
  1079.  */
  1080. keymapinit() {
  1081.     register SYMBOL    *sp;
  1082.     register KEYTAB    *kp;
  1083.     register int    i;
  1084.  
  1085.     for (i=0; i<NKEYS; ++i)
  1086.         binding[i] = NULL;
  1087.     for (kp = &key[0]; kp < &key[NKEY]; ++kp)
  1088.         keyadd(kp->k_key, kp->k_funcp, kp->k_name);
  1089.     keydup((KEY) (KCTLX|KCTRL|'G'),    "keyboard-quit");
  1090.     keydup((KEY) (KMETA|KCTRL|'G'),    "keyboard-quit");
  1091.     keyadd((KEY) (KMETA|0x7F), delbword,
  1092.                 "backward-kill-word");
  1093.     keyadd((KEY) 0x7F, backdel,    "backward-delete-char");
  1094.     /*
  1095.      * add duplicates (GNU-stuff)
  1096.      */
  1097.     keydup((KEY) (KCTLX|KCTRL|'Z'), "suspend-emacs");
  1098.     /*
  1099.      * Should be bound by "tab" already.
  1100.      */
  1101.     if ((sp=symlookup("self-insert-command")) == NULL)
  1102.         panic("no self-insert-command in keymapinit");
  1103.     for (i=0x20; i<0x7F; ++i) {
  1104.         if (binding[i] != NULL)
  1105.             panic("nonull binding in keymapinit");
  1106.         binding[i] = sp;
  1107.     }
  1108.     ttykeymapinit();
  1109. #ifdef    HASH
  1110.     /* Link up the symbol table entries    */
  1111.     for (sp = symbol[i = 0]; i < NSHASH-1; sp = sp->s_symp)
  1112.         if (sp->s_symp == NULL) sp->s_symp = symbol[++i];
  1113. #endif            
  1114. }
  1115.  
  1116. /*
  1117.  * Create a new builtin function "name"
  1118.  * with function "funcp". If the "new" is a real
  1119.  * key, bind it as a side effect. All errors
  1120.  * are fatal.
  1121.  */
  1122. keyadd(new, funcp, name) register KEY new; int (*funcp)(); char *name; {
  1123.     register SYMBOL    *sp;
  1124. #ifdef    HASH
  1125.     register int    hash;
  1126. #endif
  1127.  
  1128.     if ((sp=(SYMBOL *)malloc(sizeof(SYMBOL))) == NULL)
  1129.         panic("No memory");
  1130. #ifdef    HASH
  1131.     hash = symhash(name);
  1132.     if (symbol[hash] == NULL) sp->s_flags |= SFEND;
  1133.     sp->s_symp = symbol[hash];
  1134.     symbol[hash] = sp;
  1135. #else
  1136.     sp->s_symp = symbol[0];
  1137.         symbol[0] = sp;
  1138. #endif
  1139.     sp->s_name = name;
  1140.     sp->s_funcp = funcp;
  1141.     if (new >= 0) {                /* Bind this key.    */
  1142.         if (binding[new] != NULL)
  1143.             panic("rebinding old symbol");
  1144.         binding[new] = sp;
  1145.     }
  1146. }
  1147.  
  1148. /*
  1149.  * Bind key "new" to the existing
  1150.  * routine "name". If the name cannot be found,
  1151.  * or the key is already bound, abort.
  1152.  */
  1153. keydup(new, name) register KEY new; char *name; {
  1154.     register SYMBOL    *sp;
  1155.  
  1156.     if (binding[new]!=NULL || (sp=symlookup(name))==NULL) {
  1157. #ifdef    KEYDUP_ERROR
  1158.         fprintf (stderr, "keydup: binding[%d] = %x",
  1159.                 new, binding[new]);
  1160.         fprintf (stderr, " and symlookup(%s) == %x\n", name, sp);
  1161. #endif
  1162.         panic("keydup");
  1163.     }
  1164.     binding[new] = sp;
  1165. }
  1166. SHAR_EOF
  1167. fi # end of overwriting check
  1168. if test -f 'window.c'
  1169. then
  1170.     echo shar: will not over-write existing file "'window.c'"
  1171. else
  1172. cat << \SHAR_EOF > 'window.c'
  1173. /*
  1174.  *        Window handling.
  1175.  */
  1176. #include    "def.h"
  1177.  
  1178. /*
  1179.  * Reposition dot in the current
  1180.  * window to line "n". If the argument is
  1181.  * positive, it is that line. If it is negative it
  1182.  * is that line from the bottom. If it is 0 the window
  1183.  * is centered (this is what the standard redisplay code
  1184.  * does).  If GOSREC is undefined, default is 0, so it acts like GNU.
  1185.  * If GOSREC is defined, with no argument it defaults to 1
  1186.  * and works like in Gosling.
  1187.  */
  1188. /*ARGSUSED*/
  1189. reposition(f, n, k) {
  1190. #ifndef    GOSREC
  1191.     curwp->w_force = ((f == FALSE) ? 0 : n) ;
  1192. #else
  1193.     curwp->w_force = n;
  1194. #endif
  1195.     curwp->w_flag |= WFFORCE;
  1196.     sgarbf = TRUE;
  1197.     return (TRUE);
  1198. }
  1199.  
  1200. /*
  1201.  * Refresh the display. A call is made to the
  1202.  * "ttresize" entry in the terminal handler, which tries
  1203.  * to reset "nrow" and "ncol". They will, however, never
  1204.  * be set outside of the NROW or NCOL range. If the display
  1205.  * changed size, arrange that everything is redone, then
  1206.  * call "update" to fix the display. We do this so the
  1207.  * new size can be displayed. In the normal case the
  1208.  * call to "update" in "main.c" refreshes the screen,
  1209.  * and all of the windows need not be recomputed.
  1210.  * Note that when you get to the "display unusable"
  1211.  * message, the screen will be messed up. If you make
  1212.  * the window bigger again, and send another command,
  1213.  * everything will get fixed!
  1214.  */
  1215. /*ARGSUSED*/
  1216. refresh(f, n, k) {
  1217.     register WINDOW    *wp;
  1218.     register int    oldnrow;
  1219.     register int    oldncol;
  1220.  
  1221.     oldnrow = nrow;
  1222.     oldncol = ncol;
  1223.     ttresize();
  1224.     if (nrow!=oldnrow || ncol!=oldncol) {
  1225.         wp = wheadp;            /* Find last.        */
  1226.         while (wp->w_wndp != NULL)
  1227.             wp = wp->w_wndp;
  1228.         if (nrow < wp->w_toprow+3) {    /* Check if too small.    */
  1229.             ewprintf("Display unusable");
  1230.             return (FALSE);
  1231.         }        
  1232.         wp->w_ntrows = nrow-wp->w_toprow-2;
  1233.         sgarbf = TRUE;
  1234.         update();
  1235.         if (kbdmop == NULL) ewprintf("New size %d by %d", nrow, ncol);
  1236.     } else
  1237.         sgarbf = TRUE;
  1238.     return (TRUE);
  1239. }
  1240.  
  1241. /*
  1242.  * The command to make the next
  1243.  * window (next => down the screen)
  1244.  * the current window. There are no real
  1245.  * errors, although the command does
  1246.  * nothing if there is only 1 window on
  1247.  * the screen.
  1248.  */
  1249. /*ARGSUSED*/
  1250. nextwind(f, n, k) {
  1251.     register WINDOW    *wp;
  1252.  
  1253.     if ((wp=curwp->w_wndp) == NULL)
  1254.         wp = wheadp;
  1255.     curwp = wp;
  1256.     curbp = wp->w_bufp;
  1257.     return (TRUE);
  1258. }
  1259.  
  1260. /*
  1261.  * This command makes the previous
  1262.  * window (previous => up the screen) the
  1263.  * current window. There arn't any errors,
  1264.  * although the command does not do a lot
  1265.  * if there is 1 window.
  1266.  */
  1267. /*ARGSUSED*/
  1268. prevwind(f, n, k) {
  1269.     register WINDOW    *wp1;
  1270.     register WINDOW    *wp2;
  1271.  
  1272.     wp1 = wheadp;
  1273.     wp2 = curwp;
  1274.     if (wp1 == wp2)
  1275.         wp2 = NULL;
  1276.     while (wp1->w_wndp != wp2)
  1277.         wp1 = wp1->w_wndp;
  1278.     curwp = wp1;
  1279.     curbp = wp1->w_bufp;
  1280.     return (TRUE);
  1281. }
  1282.  
  1283. /*
  1284.  * This command makes the current
  1285.  * window the only window on the screen.
  1286.  * Try to set the framing
  1287.  * so that "." does not have to move on
  1288.  * the display. Some care has to be taken
  1289.  * to keep the values of dot and mark
  1290.  * in the buffer structures right if the
  1291.  * distruction of a window makes a buffer
  1292.  * become undisplayed.
  1293.  */
  1294. /*ARGSUSED*/
  1295. onlywind(f, n, k) {
  1296.     register WINDOW    *wp;
  1297.     register LINE    *lp;
  1298.     register int    i;
  1299.  
  1300.     while (wheadp != curwp) {
  1301.         wp = wheadp;
  1302.         wheadp = wp->w_wndp;
  1303.         if (--wp->w_bufp->b_nwnd == 0) {
  1304.             wp->w_bufp->b_dotp  = wp->w_dotp;
  1305.             wp->w_bufp->b_doto  = wp->w_doto;
  1306.             wp->w_bufp->b_markp = wp->w_markp;
  1307.             wp->w_bufp->b_marko = wp->w_marko;
  1308.         }
  1309.         free((char *) wp);
  1310.     }
  1311.     while (curwp->w_wndp != NULL) {
  1312.         wp = curwp->w_wndp;
  1313.         curwp->w_wndp = wp->w_wndp;
  1314.         if (--wp->w_bufp->b_nwnd == 0) {
  1315.             wp->w_bufp->b_dotp  = wp->w_dotp;
  1316.             wp->w_bufp->b_doto  = wp->w_doto;
  1317.             wp->w_bufp->b_markp = wp->w_markp;
  1318.             wp->w_bufp->b_marko = wp->w_marko;
  1319.         }
  1320.         free((char *) wp);
  1321.     }
  1322.     lp = curwp->w_linep;
  1323.     i  = curwp->w_toprow;
  1324.     while (i!=0 && lback(lp)!=curbp->b_linep) {
  1325.         --i;
  1326.         lp = lback(lp);
  1327.     }
  1328.     curwp->w_toprow = 0;
  1329.     curwp->w_ntrows = nrow-2;        /* 2 = mode, echo.    */
  1330.     curwp->w_linep  = lp;
  1331.     curwp->w_flag  |= WFMODE|WFHARD;
  1332.     return (TRUE);
  1333. }
  1334.  
  1335. /*
  1336.  * Split the current window. A window
  1337.  * smaller than 3 lines cannot be split.
  1338.  * The only other error that is possible is
  1339.  * a "malloc" failure allocating the structure
  1340.  * for the new window.
  1341.  */
  1342. /*ARGSUSED*/
  1343. splitwind(f, n, k) {
  1344.     register WINDOW    *wp;
  1345.     register LINE    *lp;
  1346.     register int    ntru;
  1347.     register int    ntrd;
  1348.     int        ntrl;
  1349.     WINDOW        *wp1, *wp2;
  1350.  
  1351.     if (curwp->w_ntrows < 3) {
  1352.         ewprintf("Cannot split a %d line window", curwp->w_ntrows);
  1353.         return (FALSE);
  1354.     }
  1355.     if ((wp = (WINDOW *)malloc(sizeof(WINDOW))) == NULL) {
  1356.         ewprintf("Can't get %d", sizeof(WINDOW));
  1357.         return (FALSE);
  1358.     }
  1359.     ++curbp->b_nwnd;            /* Displayed twice.    */
  1360.     wp->w_bufp  = curbp;
  1361.     wp->w_dotp  = curwp->w_dotp;
  1362.     wp->w_doto  = curwp->w_doto;
  1363.     wp->w_markp = curwp->w_markp;
  1364.     wp->w_marko = curwp->w_marko;
  1365.     wp->w_flag  = 0;
  1366.     wp->w_force = 0;
  1367.     ntru = (curwp->w_ntrows-1) / 2;        /* Upper size        */
  1368.     ntrl = (curwp->w_ntrows-1) - ntru;    /* Lower size        */
  1369.     lp = curwp->w_linep;
  1370.     ntrd = 0;
  1371.     while (lp != curwp->w_dotp) {
  1372.         ++ntrd;
  1373.         lp = lforw(lp);
  1374.     }
  1375.     lp = curwp->w_linep;
  1376.     if (ntrd <= ntru) {            /* Old is upper window.    */
  1377.         if (ntrd == ntru)        /* Hit mode line.    */
  1378.             lp = lforw(lp);
  1379.         curwp->w_ntrows = ntru;
  1380.         wp->w_wndp = curwp->w_wndp;
  1381.         curwp->w_wndp = wp;
  1382.         wp->w_toprow = curwp->w_toprow+ntru+1;
  1383.         wp->w_ntrows = ntrl;
  1384.     } else {                /* Old is lower window    */
  1385.         wp1 = NULL;
  1386.         wp2 = wheadp;
  1387.         while (wp2 != curwp) {
  1388.             wp1 = wp2;
  1389.             wp2 = wp2->w_wndp;
  1390.         }
  1391.         if (wp1 == NULL)
  1392.             wheadp = wp;
  1393.         else
  1394.             wp1->w_wndp = wp;
  1395.         wp->w_wndp   = curwp;
  1396.         wp->w_toprow = curwp->w_toprow;
  1397.         wp->w_ntrows = ntru;
  1398.         ++ntru;                /* Mode line.        */
  1399.         curwp->w_toprow += ntru;
  1400.         curwp->w_ntrows  = ntrl;
  1401.         while (ntru--)
  1402.             lp = lforw(lp);
  1403.     }
  1404.     curwp->w_linep = lp;            /* Adjust the top lines    */
  1405.     wp->w_linep = lp;            /* if necessary.    */
  1406.     curwp->w_flag |= WFMODE|WFHARD;
  1407.     wp->w_flag |= WFMODE|WFHARD;
  1408.     return (TRUE);
  1409. }
  1410.  
  1411. /*
  1412.  * Enlarge the current window.
  1413.  * Find the window that loses space. Make
  1414.  * sure it is big enough. If so, hack the window
  1415.  * descriptions, and ask redisplay to do all the
  1416.  * hard work. You don't just set "force reframe"
  1417.  * because dot would move.
  1418.  */
  1419. /*ARGSUSED*/
  1420. enlargewind(f, n, k) {
  1421.     register WINDOW    *adjwp;
  1422.     register LINE    *lp;
  1423.     register int    i;
  1424.  
  1425.     if (n < 0)
  1426.         return (shrinkwind(f, -n, KRANDOM));
  1427.     if (wheadp->w_wndp == NULL) {
  1428.         ewprintf("Only one window");
  1429.         return (FALSE);
  1430.     }
  1431.     if ((adjwp=curwp->w_wndp) == NULL) {
  1432.         adjwp = wheadp;
  1433.         while (adjwp->w_wndp != curwp)
  1434.             adjwp = adjwp->w_wndp;
  1435.     }
  1436.     if (adjwp->w_ntrows <= n) {
  1437.         ewprintf("Impossible change");
  1438.         return (FALSE);
  1439.     }
  1440.     if (curwp->w_wndp == adjwp) {        /* Shrink below.    */
  1441.         lp = adjwp->w_linep;
  1442.         for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  1443.             lp = lforw(lp);
  1444.         adjwp->w_linep  = lp;
  1445.         adjwp->w_toprow += n;
  1446.     } else {                /* Shrink above.    */
  1447.         lp = curwp->w_linep;
  1448.         for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  1449.             lp = lback(lp);
  1450.         curwp->w_linep  = lp;
  1451.         curwp->w_toprow -= n;
  1452.     }
  1453.     curwp->w_ntrows += n;
  1454.     adjwp->w_ntrows -= n;
  1455.     curwp->w_flag |= WFMODE|WFHARD;
  1456.     adjwp->w_flag |= WFMODE|WFHARD;
  1457.     return (TRUE);
  1458. }
  1459.  
  1460. /*
  1461.  * Shrink the current window.
  1462.  * Find the window that gains space. Hack at
  1463.  * the window descriptions. Ask the redisplay to
  1464.  * do all the hard work.
  1465.  */
  1466. shrinkwind(f, n, k) {
  1467.     register WINDOW    *adjwp;
  1468.     register LINE    *lp;
  1469.     register int    i;
  1470.  
  1471.     if (n < 0)
  1472.         return (enlargewind(f, -n, KRANDOM));
  1473.     if (wheadp->w_wndp == NULL) {
  1474.         ewprintf("Only one window");
  1475.         return (FALSE);
  1476.     }
  1477.     /*
  1478.      * Bit of flakiness - KRANDOM means it was an internal call, and
  1479.      * to be trusted implicitly about sizes.
  1480.      */
  1481.     if (k != KRANDOM && curwp->w_ntrows <= n) {
  1482.         ewprintf("Impossible change");
  1483.         return (FALSE);
  1484.     }
  1485.     if ((adjwp=curwp->w_wndp) == NULL) {
  1486.         adjwp = wheadp;
  1487.         while (adjwp->w_wndp != curwp)
  1488.             adjwp = adjwp->w_wndp;
  1489.     }
  1490.     if (curwp->w_wndp == adjwp) {        /* Grow below.        */
  1491.         lp = adjwp->w_linep;
  1492.         for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  1493.             lp = lback(lp);
  1494.         adjwp->w_linep  = lp;
  1495.         adjwp->w_toprow -= n;
  1496.     } else {                /* Grow above.        */
  1497.         lp = curwp->w_linep;
  1498.         for (i=0; i<n && lp!=curbp->b_linep; ++i)
  1499.             lp = lforw(lp);
  1500.         curwp->w_linep  = lp;
  1501.         curwp->w_toprow += n;
  1502.     }
  1503.     curwp->w_ntrows -= n;
  1504.     adjwp->w_ntrows += n;
  1505.     curwp->w_flag |= WFMODE|WFHARD;
  1506.     adjwp->w_flag |= WFMODE|WFHARD;
  1507.     return (TRUE);
  1508. }
  1509.  
  1510. /*
  1511.  * Delete current window. Call shrink-window to do the screen
  1512.  * updating, then throw away the window.
  1513.  */
  1514. /*ARGSUSED*/
  1515. delwind(f, n, k) {
  1516.     register WINDOW    *wp, *nwp;
  1517.  
  1518.     wp = curwp;            /* Cheap...        */
  1519.     /* shrinkwind returning false means only one window... */
  1520.     if (shrinkwind(FALSE, wp->w_ntrows + 1, KRANDOM) == FALSE)
  1521.         return FALSE;
  1522.     if (--wp->w_bufp->b_nwnd == 0) {
  1523.         wp->w_bufp->b_dotp  = wp->w_dotp;
  1524.         wp->w_bufp->b_doto  = wp->w_doto;
  1525.         wp->w_bufp->b_markp = wp->w_markp;
  1526.         wp->w_bufp->b_marko = wp->w_marko;
  1527.     }
  1528.     /* since shrinkwind did't crap out, we know we have a second window */
  1529.     if (wp == wheadp) wheadp = curwp = wp->w_wndp;
  1530.     else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
  1531.     curbp = curwp->w_bufp;
  1532.     for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
  1533.         if (nwp->w_wndp == wp) {
  1534.             nwp->w_wndp = wp->w_wndp;
  1535.             break ;
  1536.         }
  1537.     free((char *) wp);
  1538.     return TRUE;
  1539. }
  1540. /*
  1541.  * Pick a window for a pop-up.
  1542.  * Split the screen if there is only
  1543.  * one window. Pick the uppermost window that
  1544.  * isn't the current window. An LRU algorithm
  1545.  * might be better. Return a pointer, or
  1546.  * NULL on error.
  1547.  */
  1548. WINDOW    *
  1549. wpopup() {
  1550.     register WINDOW    *wp;
  1551.  
  1552.     if (wheadp->w_wndp == NULL
  1553.     && splitwind(FALSE, 0, KRANDOM) == FALSE)
  1554.         return (NULL);
  1555.     wp = wheadp;                /* Find window to use    */
  1556.     while (wp!=NULL && wp==curwp)
  1557.         wp = wp->w_wndp;
  1558.     return (wp);
  1559. }
  1560. SHAR_EOF
  1561. fi # end of overwriting check
  1562. if test -f 'tty/termcap/tty.c'
  1563. then
  1564.     echo shar: will not over-write existing file "'tty/termcap/tty.c'"
  1565. else
  1566. cat << \SHAR_EOF > 'tty/termcap/tty.c'
  1567. /*
  1568.  * Termcap/terminfo display driver
  1569.  *
  1570.  * Termcap is a terminal information database and routines to describe 
  1571.  * terminals on most UNIX systems.  Many other systems have adopted
  1572.  * this as a reasonable way to allow for widly varying and ever changing
  1573.  * varieties of terminal types.  This should be used where practical.
  1574.  */
  1575. /* Known problems:
  1576.  *    tputs is always called with the number of lines affected set to
  1577.  *    one.  Therefore, padding may be insufficient on some sequences
  1578.  *    dispite termcap being set up correctly.
  1579.  *
  1580.  *    If you have a terminal with no clear to end of screen and
  1581.  *    memory of lines below the ones visible on the screen, display
  1582.  *    will be wrong in some cases.  I doubt that any such terminal
  1583.  *    was ever made, but I thought everyone with delete line would
  1584.  *    have clear to end of screen too...
  1585.  *
  1586.  *    Code for terminals without clear to end of screen and/or clear
  1587.  *    to end of line has not been extensivly tested.
  1588.  *
  1589.  *    Cost calculations are very rough.  Costs of insert/delete line
  1590.  *    may be far from the truth.  This is accentuated by display.c
  1591.  *    not knowing about multi-line insert/delete.
  1592.  *
  1593.  *    Using scrolling region vs insert/delete line should probably
  1594.  *    be based on cost rather than the assuption that scrolling
  1595.  *    region operations look better.
  1596.  */
  1597. #include    "def.h"
  1598.  
  1599. #define    BEL    0x07            /* BEL character.        */
  1600. #define    LF    0x0A            /* Line feed.            */
  1601.  
  1602. extern    int    ttrow;
  1603. extern    int    ttcol;
  1604. extern    int    tttop;
  1605. extern    int    ttbot;
  1606. extern    int    tthue;
  1607.  
  1608. int    tceeol;            /* Costs are set later */
  1609. int    tcinsl;
  1610. int    tcdell;
  1611.  
  1612. static    int    insdel;        /* Do we have both insert & delete line? */
  1613.  
  1614. char    *tgetstr();
  1615. char    *tgoto();
  1616. int    ttputc();
  1617.  
  1618. #define TCAPSLEN 1024
  1619.  
  1620. char tcapbuf[TCAPSLEN];
  1621.  
  1622. /* PC, UP, and BC are used by termlib, so must be extern and have these
  1623.  * names unless you have a non-standard termlib.
  1624.  */
  1625.  
  1626. int    LI;            /* standard # lines */
  1627. char    PC,
  1628.         *CM,
  1629.         *CE,
  1630.         *UP,
  1631.     *BC,
  1632.     *IM,            /* insert mode */
  1633.     *IC,            /* insert a single space */
  1634.     *EI,            /* end insert mode */
  1635.     *DC,
  1636.     *AL,            /* add line */
  1637.     *DL,            /* del line */
  1638.     *pAL,            /* parameterized add line */
  1639.     *pDL,            /* parameterized delete line */
  1640.     *TI,            /* term init -- start using cursor motion */
  1641.     *TE,            /* term end --- end using cursor motion */
  1642.     *SO,
  1643.     *SE,
  1644.         *CD,
  1645.     *CS,            /* set scroll region            */
  1646.     *SR;            /* back index (used with scroll region    */
  1647. #ifdef    XKEYS
  1648. char    *K[NFKEYS],        /* other function key codes        */
  1649.     *L[NFKEYS],        /* labels for other functions keys    */
  1650.     *KS, *KE,        /* enter keypad mode, exit keypad mode    */
  1651.     *KH, *KU, *KD, *KL, *KR; /* home, arrow keys            */
  1652. #endif
  1653. int    SG;    /* number of glitches, 0 for invisable, -1 for none    */
  1654.     /* (yes virginia, there are terminals with invisible glitches)    */
  1655.  
  1656. /*
  1657.  * Initialize the terminal when the editor
  1658.  * gets started up.
  1659.  */
  1660. static char tcbuf[1024];
  1661.  
  1662. ttinit() {
  1663.         char *getenv();
  1664.         char *t, *p, *tgetstr();
  1665.         char *tv_stype;
  1666. #ifdef    XKEYS
  1667.     char kname[3], lname[3];
  1668.     int i;
  1669. #endif
  1670.  
  1671. #ifdef    VAXC
  1672.         if ((tv_stype = trnlnm("TERM")) == NULL)
  1673. #else
  1674.         if ((tv_stype = getenv("TERM")) == NULL)/* Don't want VAX C getenv() */
  1675. #endif
  1676.                 panic("Environment variable TERM not defined!");
  1677.  
  1678.         if((tgetent(tcbuf, tv_stype)) != 1)
  1679.     {
  1680.         (VOID) strcpy(tcbuf, "Unknown terminal type ");
  1681.         (VOID) strcat(tcbuf, tv_stype);
  1682.                 panic(tcbuf);
  1683.         }
  1684.  
  1685.         p = tcapbuf;
  1686.         t = tgetstr("pc", &p);
  1687.         if(t) PC = *t;
  1688.  
  1689.     LI = tgetnum("li");
  1690.         CD = tgetstr("cd", &p);
  1691.         CM = tgetstr("cm", &p);
  1692.         CE = tgetstr("ce", &p);
  1693.         UP = tgetstr("up", &p);
  1694.     BC = tgetstr("bc", &p);
  1695.     IM = tgetstr("im", &p);
  1696.     IC = tgetstr("ic", &p);
  1697.     EI = tgetstr("ei", &p);
  1698.     DC = tgetstr("dc", &p);
  1699.     AL = tgetstr("al", &p);
  1700.     DL = tgetstr("dl", &p);
  1701.     pAL= tgetstr("AL", &p);    /* parameterized insert and del. line */
  1702.     pDL= tgetstr("DL", &p);
  1703.     TI = tgetstr("ti", &p);
  1704.     TE = tgetstr("te", &p);
  1705.     SO = tgetstr("so", &p);
  1706.     SE = tgetstr("se", &p);
  1707.     CS = tgetstr("cs", &p); /* set scrolling region */
  1708.     SR = tgetstr("sr", &p);
  1709.     SG = tgetnum("sg");    /* standout glitch     */
  1710. #ifdef    XKEYS
  1711.     /* get the 10 standard termcap keys */
  1712.     strcpy(kname,"kx");
  1713.     strcpy(lname,"lx");
  1714.     for (i = 0; i < 10; i++) {
  1715.         kname[1] = i + '0';
  1716.         K[i] = tgetstr(kname, &p);
  1717.         lname[1] = i + '0';
  1718.         L[i] = tgetstr(lname, &p);
  1719.     }
  1720.     /* Hack to get another bunch */
  1721.     strcpy(kname,"Kx");
  1722.     strcpy(lname,"Lx");
  1723.     for (i = 0; i < 10; i++) {
  1724.         kname[1] = i + '0';
  1725.         K[10 + i] = tgetstr(kname, &p);
  1726.         lname[1] = i + '0';
  1727.         L[10 + i] = tgetstr(lname, &p);
  1728.     }
  1729.  
  1730.     /* Get the rest of the sequences */
  1731.     KS = tgetstr("ks", &p);
  1732.     KE = tgetstr("ke", &p);
  1733.     KH = tgetstr("kh", &p);
  1734.     KU = tgetstr("ku", &p);
  1735.     KD = tgetstr("kd", &p);
  1736.     KL = tgetstr("kl", &p);
  1737.     KR = tgetstr("kr", &p);
  1738. #endif
  1739.  
  1740.         if(CM == NULL || UP == NULL)
  1741.             panic("This terminal is to stupid to run MicroGnuEmacs\n");
  1742.     ttresize();            /* set nrow & ncol    */
  1743.  
  1744.     /* watch out for empty capabilities (sure to be wrong)    */
  1745.     if (CE && !*CE) CE = NULL;
  1746.     if (CS && !*CS) CS = NULL;
  1747.     if (SR && !*SR) SR = NULL;
  1748.     if (AL && !*AL) AL = NULL;
  1749.     if (DL && !*DL) DL = NULL;
  1750.     if (pAL && !*pAL) pAL = NULL;
  1751.     if (pDL && !*pDL) pDL = NULL;
  1752.     if (CD && !*CD) CD = NULL;
  1753.  
  1754.     if(!CE)    tceeol = ncol;
  1755.     else     tceeol = charcost(CE);
  1756.  
  1757.     /* Estimate cost of inserting a line */
  1758.     if (CS && SR)    tcinsl = charcost(CS)*2 + charcost(SR);
  1759.     else if (pAL)   tcinsl = charcost(pAL);
  1760.     else if (AL)    tcinsl = charcost(AL);
  1761.     else        tcinsl = NROW * NCOL;    /* make this cost high enough */
  1762.  
  1763.     /* Estimate cost of deleting a line */
  1764.     if (CS)        tcdell = charcost(CS)*2 + 1;
  1765.     else if (pDL)   tcdell = charcost(pDL);
  1766.     else if (DL)    tcdell = charcost(DL);
  1767.     else        tcdell = NROW * NCOL;    /* make this cost high enough */
  1768.  
  1769.     /* Flag to indicate that we can both insert and delete lines */
  1770.     insdel = (AL || pAL) && (DL || pDL);
  1771.  
  1772.         if (p >= &tcapbuf[TCAPSLEN])
  1773.         panic("Terminal description too big!\n");
  1774.     if (TI && *TI) putpad (TI);    /* init the term */
  1775. }
  1776.  
  1777. /*
  1778.  * Clean up the terminal, in anticipation of
  1779.  * a return to the command interpreter. This is a no-op
  1780.  * on the ANSI display. On the SCALD display, it sets the
  1781.  * window back to half screen scrolling. Perhaps it should
  1782.  * query the display for the increment, and put it
  1783.  * back to what it was.
  1784.  */
  1785. tttidy() {
  1786.     if (TE && *TE) putpad (TE);    /* set the term back to normal mode */
  1787. #ifdef    XKEYS
  1788.     ttykeymaptidy();
  1789. #endif
  1790. }
  1791.  
  1792. /*
  1793.  * Move the cursor to the specified
  1794.  * origin 0 row and column position. Try to
  1795.  * optimize out extra moves; redisplay may
  1796.  * have left the cursor in the right
  1797.  * location last time!
  1798.  */
  1799. ttmove(row, col) {
  1800.     char        *tgoto();
  1801.  
  1802.     if (ttrow!=row || ttcol!=col) {
  1803.     putpad(tgoto(CM, col, row));
  1804.     ttrow = row;
  1805.     ttcol = col;
  1806.     }
  1807. }
  1808.  
  1809. /*
  1810.  * Erase to end of line.
  1811.  */
  1812. tteeol() {
  1813.     if(CE) putpad(CE);
  1814.     else {
  1815.     register int i=ncol-ttcol;
  1816.     while(i--) ttputc(" ");
  1817.     ttrow = ttcol = HUGE;
  1818.     }
  1819. }
  1820.  
  1821. /*
  1822.  * Erase to end of page.
  1823.  */
  1824. tteeop() {
  1825.     if(CD) putpad(CD);
  1826.     else {
  1827.         putpad(CE);
  1828.     if (insdel) ttdell(ttrow + 1, LI, LI - ttrow - 1);
  1829.     else {        /* do it by hand */
  1830.         register int line;
  1831.         for (line = ttrow + 1; line <= LI; ++line) {
  1832.             ttmove(line, 0);
  1833.         tteeol();
  1834.         }
  1835.     }
  1836.     ttrow = ttcol = HUGE;
  1837.     }
  1838. }
  1839.  
  1840. /*
  1841.  * Make a noise.
  1842.  */
  1843. ttbeep() {
  1844.     ttputc(BEL);
  1845.     ttflush();
  1846. }
  1847.  
  1848. /*
  1849.  * Insert nchunk blank line(s) onto the
  1850.  * screen, scrolling the last line on the
  1851.  * screen off the bottom.  Use the scrolling
  1852.  * region if possible for a smoother display.
  1853.  * If no scrolling region, use a set
  1854.  * of insert and delete line sequences
  1855.  */
  1856. ttinsl(row, bot, nchunk) {
  1857.     register int    i;
  1858.     
  1859.     if (row == bot) {        /* Case of one line insert is     */
  1860.     ttmove(row, 0);        /*    special            */
  1861.     tteeol();
  1862.     return;
  1863.     }
  1864.     if (CS && SR) {        /* Use scroll region and back index    */
  1865.     ttwindow(row,bot);
  1866.     ttmove(row, 0);
  1867.     while (nchunk--) putpad(SR);
  1868.     ttnowindow();
  1869.     return;
  1870.     } else if (insdel) {
  1871.     ttmove(1+bot-nchunk, 0);
  1872.     if (pDL) putpad (tgoto(pDL, 0, nchunk));
  1873.     else for (i=0; i<nchunk; i++)    /* For all lines in the chunk    */
  1874.         putpad(DL);
  1875.     ttmove(row, 0);
  1876.     if (pAL) putpad (tgoto(pAL, 0, nchunk));
  1877.     else for (i=0; i<nchunk; i++)    /* For all lines in the chunk    */
  1878.         putpad(AL);
  1879.     ttrow = HUGE;
  1880.     ttcol = HUGE;
  1881.     } else panic("ttinsl: Can't insert/delete line");
  1882. }
  1883.  
  1884. /*
  1885.  * Delete nchunk line(s) from "row", replacing the
  1886.  * bottom line on the screen with a blank line. 
  1887.  * Unless we're using the scrolling region, this is 
  1888.  * done with a crafty sequences of insert and delete 
  1889.  * lines.  The presence of the echo area makes a
  1890.  * boundry condition go away.
  1891.  */
  1892. ttdell(row, bot, nchunk)
  1893. {
  1894.     register int    i;
  1895.     
  1896.     if (row == bot) {        /* One line special case    */
  1897.     ttmove(row, 0);
  1898.     tteeol();
  1899.     return;
  1900.     }
  1901.     if (CS) {            /* scrolling region    */
  1902.     ttwindow(row, bot);
  1903.     ttmove(bot, 0);
  1904.     while (nchunk--) ttputc(LF);
  1905.     ttnowindow();
  1906.     }
  1907.     else if(insdel) {
  1908.     ttmove(row, 0);            /* Else use insert/delete line    */
  1909.     if (pDL) putpad (tgoto(pDL, 0, nchunk));
  1910.     else for (i=0; i<nchunk; i++)    /* For all lines in the chunk    */
  1911.         putpad(DL);
  1912.     ttmove(1+bot-nchunk,0);
  1913.     if (pAL) putpad (tgoto(pAL, 0, nchunk));
  1914.     else for (i=0; i<nchunk; i++)    /* For all lines in the chunk    */
  1915.         putpad(AL);
  1916.     ttrow = HUGE;
  1917.     ttcol = HUGE;
  1918.     } else panic("ttdell: Can't insert/delete line");
  1919. }
  1920.  
  1921. /*
  1922.  * This routine sets the scrolling window
  1923.  * on the display to go from line "top" to line
  1924.  * "bot" (origin 0, inclusive). The caller checks
  1925.  * for the pathalogical 1 line scroll window that
  1926.  * doesn't work right, and avoids it. The "ttrow"
  1927.  * and "ttcol" variables are set to a crazy value
  1928.  * to ensure that the next call to "ttmove" does
  1929.  * not turn into a no-op (the window adjustment
  1930.  * moves the cursor).
  1931.  * 
  1932.  */
  1933. ttwindow(top, bot)
  1934. {
  1935.     if (CS && (tttop!=top || ttbot!=bot)) {
  1936.         putpad(tgoto(CS, bot, top));
  1937.         ttrow = HUGE;            /* Unknown.        */
  1938.         ttcol = HUGE;
  1939.         tttop = top;            /* Remember region.    */
  1940.         ttbot = bot;
  1941.     }
  1942. }
  1943.  
  1944. /*
  1945.  * Switch to full screen scroll. This is
  1946.  * used by "spawn.c" just before is suspends the
  1947.  * editor, and by "display.c" when it is getting ready
  1948.  * to exit.  This function gets to full screen scroll 
  1949.  * by telling the terminal to set a scrolling regin
  1950.  * that is LI or nrow rows high, whichever is larger.
  1951.  * This behavior seems to work right on systems
  1952.  * where you can set your terminal size.
  1953.  */
  1954. ttnowindow()
  1955. {
  1956.     if (CS) {
  1957.     putpad(tgoto(CS, (nrow > LI ? nrow : LI) - 1, 0));
  1958.     ttrow = HUGE;            /* Unknown.        */
  1959.     ttcol = HUGE;
  1960.     tttop = HUGE;            /* No scroll region.    */
  1961.     ttbot = HUGE;
  1962.     }
  1963. }
  1964.  
  1965. /*
  1966.  * Set the current writing color to the
  1967.  * specified color. Watch for color changes that are
  1968.  * not going to do anything (the color is already right)
  1969.  * and don't send anything to the display.
  1970.  * The rainbow version does this in putline.s on a
  1971.  * line by line basis, so don't bother sending
  1972.  * out the color shift.
  1973.  */
  1974. ttcolor(color) register int color; {
  1975.     if (color != tthue) {
  1976.     if (color == CTEXT) {        /* Normal video.    */
  1977.         putpad(SE);
  1978.     } else if (color == CMODE) {    /* Reverse video.    */
  1979.         putpad(SO);
  1980.     }
  1981.     tthue = color;            /* Save the color.    */
  1982.     }
  1983. }
  1984.  
  1985. /*
  1986.  * This routine is called by the
  1987.  * "refresh the screen" command to try and resize
  1988.  * the display. The new size, which must be deadstopped
  1989.  * to not exceed the NROW and NCOL limits, it stored
  1990.  * back into "nrow" and "ncol". Display can always deal
  1991.  * with a screen NROW by NCOL. Look in "window.c" to
  1992.  * see how the caller deals with a change.
  1993.  */
  1994. ttresize() {
  1995.     setttysize();            /* found in "ttyio.c",    */
  1996.                     /* ask OS for tty size    */
  1997.     if (nrow < 1)            /* Check limits.    */
  1998.         nrow = 1;
  1999.     else if (nrow > NROW)
  2000.         nrow = NROW;
  2001.     if (ncol < 1)
  2002.         ncol = 1;
  2003.     else if (ncol > NCOL)
  2004.         ncol = NCOL;
  2005. }
  2006.  
  2007. #ifdef NO_RESIZE
  2008. static setttysize() {
  2009.     nrow = tgetnum("li");
  2010.     ncol = tgetnum("co");
  2011. }
  2012. #endif
  2013.  
  2014. static int cci;
  2015.  
  2016. static            /* fake char output for charcost() */
  2017. fakec(c) char c; {
  2018. #ifdef    lint
  2019.     c++;
  2020. #endif
  2021.     cci++;
  2022. }
  2023.  
  2024. /* calculate the cost of doing string s */
  2025. charcost (s) char *s; {
  2026.     cci = 0;
  2027.  
  2028.     tputs(s, nrow, fakec);
  2029.     return cci;
  2030. }
  2031.  
  2032. putpad(str) char *str; {
  2033.         tputs(str, 1, ttputc);
  2034. }
  2035. SHAR_EOF
  2036. fi # end of overwriting check
  2037. if test -f 'tty/termcap/readme'
  2038. then
  2039.     echo shar: will not over-write existing file "'tty/termcap/readme'"
  2040. else
  2041. cat << \SHAR_EOF > 'tty/termcap/readme'
  2042.  
  2043.     MicroGnuEmacs Termcap Terminal Capabilities
  2044.  
  2045. The termcap library needs to know where to get the terminal type and
  2046. termcap capibilities file from.  UNIX and Os9/68k users should "setenv
  2047. TERM" to their terminal type, and "setenv TERMCAP" if they are using a
  2048. non-standard termcap file.  VMS users should see AAAREADME.1ST for
  2049. information on how to define the logical names TERM and ETC to point
  2050. to the termcap definition file.  Users of other operating systems
  2051. should do the aproprate thing.  For an example of a termcap file, UNIX
  2052. users may look in /etc/termcap, Os9/68k users may look at
  2053. /dd/sys/termcap (if present), and VMS users should see the file
  2054. [.SYS.VMS.TERMCAP]TERMCAP. 
  2055.  
  2056. MicroGnuEmacs requires that certain terminal capabilities exist in the
  2057. specified termcap entry.  The "cm" (cursor motion) capability *must*
  2058. be available to use MicroGnuEmacs.  (Yes, it is possible to fake cm
  2059. with some other capibilities, but MicroGnuEmacs doesn't try.)  If your
  2060. terminal is one that uses control characters in the paramater portion
  2061. of the "cm" string, the "up" and "bc" capabilites may also be needed.
  2062. (See your termlib documentation for when this is so.)
  2063.  
  2064. If the following capabilities are available, they are used.  The AL
  2065. and DL sequences are not totally standard, but having them improves
  2066. the performance of the editor, since it doesn't have to redraw the
  2067. screen to delete a line.  They should not be used if they need control
  2068. characters as paramaters.
  2069.  
  2070.     cd    -- clear display
  2071.     ce    -- clear to eol
  2072.  
  2073.     al    -- insert 1 line
  2074.     dl    -- delete 1 line
  2075.  
  2076.     AL    -- parametrized insert line (note capitalization)
  2077.     DL    -- parametrized delete line (note capitalization)
  2078.  
  2079.     ti    -- cursor movement initialization string
  2080.     te    -- cursor movement end string
  2081.  
  2082. The cs capability is not as standard as some of the other
  2083. capibilities, but is used by MicroGnuEmacs when available.  It is used
  2084. to define a "scrolling region", which defines a window within the
  2085. screen where all the action takes place.  A newline character at the
  2086. bottom of this area scrolls the rest of the text in the area up one
  2087. line, just like the normal screen; a reverse linefeed (sr) at the top
  2088. of the window moves all the text in the area down a line.
  2089. MicroGnuEmacs does not properly handle "cs" if your terminal needs
  2090. control characters as paramaters, and in this case "cs" should not be
  2091. defined.  
  2092.  
  2093. If the cs and sr capabilities are available, the termcap driver uses
  2094. these to make the insert/delete line functions work more smoothly. If
  2095. only the cs capability is present, it is still used for the delete
  2096. line function, but not for inserting lines.
  2097.  
  2098. The definition of the cs capability is: the first parameter in the
  2099. sequence defines the first row (origin 0) that is in the scrolling
  2100. region, and the second argument defines the last row to include in the
  2101. scrolling region.
  2102.  
  2103.     cs    -- set scrolling region (arg1 = top, arg2 = bottom)
  2104.     sr    -- reverse index
  2105.  
  2106. The following capabilities provide for an enhanced (reverse-video
  2107. or otherwise rendered) mode line.  The sg entry should not be present
  2108. on terminals that do this to characters as they are placed on the
  2109. screen.  Terminals that    put a region of the screen in the standout
  2110. mode should have sg defined as numeric: :sg#0: for terminals that do
  2111. this on regions but don't take any character positions to do this,
  2112. (this may be a non-standard interprition of the meaning of sg) and the
  2113. number of character positions taken by any other terminal.
  2114.  
  2115.     so    -- enter standout mode
  2116.     se    -- leave standout mode
  2117.     sg    -- number of character positions used by standout
  2118.  
  2119.             Function Keys
  2120.  
  2121. If MicroGnuEmacs is compiled with XKEYS defined, a new feature of the
  2122. termcap driver is support for function keys, based on the termcap
  2123. entry that defines the terminal.  This may not be be deisriable in all
  2124. cases, especially those in which the terminal in use does not use ESC
  2125. as the first character of all arrow and function keys.  If you do
  2126. deside to use this feature, don't expect it to work with all terminal
  2127. types.  Those termial types it doesn't work with will have to use
  2128. modified termcaps that do not include the termcap sequences described
  2129. below to be useful with MicroGnuEmacs compiled with the XKEYS option. 
  2130. XKEYS also interferes with the proper operation of delayed prompts.
  2131.  
  2132. The termcap "standard" provides for a number of sequences that define
  2133. how to activate the function keys, what the function key sequences
  2134. are, and the names of the function keys.  The termcap driver uses the
  2135. following capabilities to parse for function key sequences:
  2136.  
  2137.     ks    -- start using function keys
  2138.     ke    -- finish using the function keypad
  2139.     kh    -- home key
  2140.     ku    -- up arrow
  2141.     kd    -- down arrow
  2142.     kl    -- left arrow
  2143.     kr    -- right arrow
  2144.     k0-k9    -- standard termcap function keys (1-10)
  2145.     l0-l9    -- labels for same
  2146.  
  2147. The following key capabilities are not standard, but are used if
  2148. they are in the termcap:
  2149.  
  2150.     K0-K9    -- function keys 10 through 19
  2151.     L0-L9    -- labels for same
  2152.  
  2153. For example, the DEC LK201 (vt200-series, VAXstation) keyboard has an
  2154. editing keypad. A VT200 termcap entry could include the following
  2155. capabilities to go into application keypad mode, set up the arrow keys,
  2156. and map the editing keypad to internal function key codes KF0-KF7:
  2157.  
  2158.     ...the beginning of the termcap entry....
  2159.     :ks=\E[?1h\E=:ke=\E[?1l\E>:\
  2160.     :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kh=\E[H:\
  2161.     :k0=\E[28~:l0=Help:\
  2162.     :k1=\E[29~:l1=Do:\
  2163.     :k2=\E[1~:l2=Find:\
  2164.     :k3=\E[2~:l3=Insert Here:\
  2165.     :k4=\E[3~:l4=Remove:\
  2166.     :k5=\E[4~:l5=Select:\
  2167.     :k6=\E[5~:l6=Prev Screen:\
  2168.     :k7=\E[6~:l7=Next Screen:\
  2169.  
  2170. There is one problem with supporting function keys: If the META
  2171. introducer key (usually ESC) is used as the initial character of a
  2172. function key sequence, how is the parser to know when the user intends
  2173. the introducer to be taken at face value?  The parser doesn't have
  2174. enough information.
  2175.  
  2176. The approach the current code takes is that if the META introducer is
  2177. the first character in a function sequence, and the second character c
  2178. isn't part of a function key sequence, the parser returns (KMETA | c).
  2179. If it sees *two* META introducers in a row, it returns one instance of
  2180. METACH. This approach is subject to discussion and debate, but it
  2181. works right most of the time.
  2182. SHAR_EOF
  2183. fi # end of overwriting check
  2184. if test -f 'tty/termcap/ttydef.h'
  2185. then
  2186.     echo shar: will not over-write existing file "'tty/termcap/ttydef.h'"
  2187. else
  2188. cat << \SHAR_EOF > 'tty/termcap/ttydef.h'
  2189. /*
  2190.  *    Termcap terminal file, nothing special, just make it big
  2191.  *    enough for windowing systems.
  2192.  */
  2193.  
  2194. #define    GOSLING            /* Compile in fancy display.    */
  2195. /* #define    MEMMAP        */    /* Not memory mapped video.    */
  2196.  
  2197. #define    NROW    66                /* Rows.            */
  2198. #define    NCOL    132            /* Columns.            */
  2199. /* #define    MOVE_STANDOUT        /* don't move in standout mode    */
  2200. #define    STANDOUT_GLITCH            /* possible standout glitch    */
  2201. #define    TERMCAP                /* for possible use in ttyio.c    */
  2202.  
  2203. /*
  2204.  * Termcap function keys.  The last 10 keys correspond to the
  2205.  * non-standard termcap entries K0-K9 (instead of k0-k9).
  2206.  */
  2207. #ifdef    XKEYS
  2208. #define    KFIRST    K01
  2209. #define KLAST    K1A
  2210.  
  2211. #define KHOME    K01
  2212. #define KDOWN    K02
  2213. #define    KUP    K03
  2214. #define    KLEFT    K04
  2215. #define    KRIGHT    K05
  2216. #define    KF0    K06
  2217. #define    KF1    K07
  2218. #define KF2    K08
  2219. #define KF3    K09
  2220. #define KF4    K0A
  2221. #define KF5    K0B
  2222. #define KF6    K0C
  2223. #define KF7    K0D
  2224. #define KF8    K0E
  2225. #define    KF9    K0F
  2226. #define KF10    K10
  2227. #define    KF11    K11
  2228. #define    KF12    K12
  2229. #define    KF13    K13
  2230. #define    KF14    K14
  2231. #define    KF15    K15
  2232. #define    KF16    K16
  2233. #define    KF17    K17
  2234. #define    KF18    K18
  2235. #define    KF19    K19
  2236. #define    KF20    K1A
  2237.  
  2238. #define    NFKEYS    20        /* # of function keys (k0-k9, K0-K9) */
  2239. #endif
  2240. SHAR_EOF
  2241. fi # end of overwriting check
  2242. #    End of shell archive
  2243. exit 0
  2244.  
  2245.